package util

import (
	"errors"
	"gopkg.in/gographics/imagick.v3/imagick"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	LibreofficeHome = "LIBREOFFICE_HOME"

)

var(
	CONVERT_ERROR = errors.New("文档转换失败")
)

//ConvertPdfToImage 转换pdf为图片格式
//@resolution:扫描精度
//@CompressionQuality:图片质量: 1~100
func PDFConvert(bookname string,format string,pageWidth uint, pageHeight uint, resolution float64) (map[int]string,error)  {

	imagesPath := make(map[int]string)
	log.Printf("originFile:[%v]",bookname)
	imagick.Initialize()
	defer imagick.Terminate()
	mw := imagick.NewMagickWand()
	//defer mw.Clear()
	defer mw.Destroy()
	path := filepath.Dir(bookname) + string(filepath.Separator)

	if err := mw.SetResolution(resolution, resolution); err != nil {
		log.Panicln("扫描精度设置失败")
		return nil,err
	}

	if err := mw.ReadImage(bookname); err != nil {
		log.Panicln("文件读取失败")
		return nil,err
	}
	// -define registry:temporary-path=/data/tmp
	//mw.SetOption("",)

	var pages = int(mw.GetNumberImages())
	log.Println("页数:", pages)
	//裁剪会使页数增加
	wg := sync.WaitGroup{}
	wg.Add(pages)
	errorChan := make(chan int,1)

	for i := 0; i < pages; i++ {
		mw.SetIteratorIndex(i)
		curImage := mw.GetImageFromMagickWand()
		curMW := imagick.NewMagickWandFromImage(curImage)
		//curMW := mw.Clone()
		go imageConvert(&wg, errorChan,imagesPath,i ,curMW ,path,format, pageWidth, pageHeight)
	}
	wg.Wait()
	// 等待所有转换完成
	select {
		case <-errorChan:
			log.Printf("转换图片失败")
			return nil, CONVERT_ERROR
		default:
			log.Printf("图片转换中。。。")
	}
	log.Println("转换完毕!")
	return imagesPath,nil
}

func imageConvert(group *sync.WaitGroup, errchan chan int,imagesPath map[int]string,i int,mw *imagick.MagickWand,path string,format string, pageWidth uint, pageHeight uint){

	log.Printf("开始转换图片[%v]" ,i)
	start := time.Now().Nanosecond()
	defer mw.Destroy()
	defer func() {
		if recover() != nil {
			errchan <- 1
		}
	}()
	defer group.Done()
	//压平图像，去掉alpha通道，防止JPG中的alpha变黑,用在ReadImage之后
	if err := mw.SetImageAlphaChannel(imagick.ALPHA_CHANNEL_REMOVE); err != nil {
		log.Printf("转换图片失败[%v]" ,i)
		errchan <- 1
		return
	}

	var filePath string
	var err error

	//如果width>height ,就裁剪成两张
	// pWidth := mw.GetImageWidth()
	// pHeight := mw.GetImageHeight()
	//需要裁剪
	//if pWidth > pHeight {
	//	//mw.ResizeImage(pageWidth*2, pageHeight, imagick.FILTER_UNDEFINED, 1.0)
	//	mw.ThumbnailImage(pageWidth*2, pageHeight)
	//	tempImage := mw.GetImageFromMagickWand()
	//	leftMw := imagick.NewMagickWandFromImage(tempImage) //由于返回的是指针,需要提前初始化,不然写完左半业tempImage就变了
	//	//左半页
	//	//mw.CropImage(pageWidth, pageHeight, 0, 0)
	//	filePath = path + strconv.Itoa(i+int(atomic.LoadInt64(addPages))) + "." + format
	//	err = mw.WriteImage(filePath)
	//	//右半页
	//	//leftMw.SetImageFormat(format)
	//	//leftMw.SetImageCompression(imagick.COMPRESSION_JPEG)
	//	//leftMw.SetImageCompressionQuality(compressionQuality)
	//	//leftMw.CropImage(pageWidth, pageHeight, int(pageWidth), 0)
	//	atomic.AddInt64(addPages,1)
	//	filePath = path + strconv.Itoa(i+int(atomic.LoadInt64(addPages))) + "." + format
	//	err = leftMw.WriteImage(filePath)
	//	leftMw.Destroy()
	//} else {
	//	if pageWidth > 0 && pageHeight > 0 {
	//		mw.ThumbnailImage(pageWidth, pageHeight)
	//	}
	//	filePath = path + strconv.Itoa(i+int(atomic.LoadInt64(addPages))) + "." + format
	//	err = mw.WriteImage(filePath)
	//}

	if pageWidth > 0 && pageHeight > 0 {
		mw.ThumbnailImage(pageWidth, pageHeight)
	}
	filePath = path + strconv.Itoa(i) + "." + format
	err = mw.WriteImage(filePath)
	if err != nil {
		log.Printf("转换图片失败：%v  %v" ,i,err)
		return
	}
	imagesPath[i] = filePath
	end := time.Now().Nanosecond()
	log.Println("输出图片：" + filePath)
	log.Printf("结束转换图片[%v],time[%v]" ,i,end-start)
}



func LibreOfficeConvert(filePath string,format string, fileId int64, pageWidth uint, pageHeight uint, resolution float64, compressionQuality uint)  (map[int]string,error) {

	libreOfficePath := os.Getenv(LibreofficeHome)
	if libreOfficePath != "" {
		libreOfficePath += string(os.PathSeparator)
	}else{
		libreOfficePath = ""
	}

	path,_ := filepath.Split(filePath)

	cmd := exec.Command(libreOfficePath + "soffice", "--headless","--convert-to pdf:writer_pdf_Export",filePath,"--outdir",path)

	stdout, err := cmd.CombinedOutput()
	if err != nil {
		log.Printf(err.Error())
		return nil, err
	}
	log.Printf("convert %s",stdout)
	lastIndex := strings.LastIndex(filePath,".")
	return PDFConvert(filePath[:lastIndex] + ".pdf",format, pageWidth, pageHeight, resolution)
}